package parser

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"save-kindle/log"
	"strings"
	"text/template"
)

type EpubParser struct {
	FileName     string
	Path         string
	MetaInfPath  string
	Oebps        string
	DataMap      *OpfEntity
	Chap         chan EpubChapter
	ParserFinish chan int
	ListSize     int
}

type EpubChapter struct {
	FileName string
	// 章节文件存储路径
	CurCount int
	// 章节标题
	Title string
	// 章节内容 按行读取
	Content []string
}

// NewEpubParser 构建解析器
func NewEpubParser(fileName string) EpubParser {
	path := fmt.Sprintf("./%s/", fileName)

	// 构建
	return EpubParser{
		FileName:    fileName,
		Path:        path,
		MetaInfPath: fmt.Sprintf("%s%s/", path, "META-INF"),
		Oebps:       fmt.Sprintf("%s%s/", path, "OEBPS"),
		DataMap: &OpfEntity{
			Title:     fileName,
			Creator:   []string{"Exler"},
			Publisher: "Exler",
		},
		Chap:         make(chan EpubChapter, 5),
		ParserFinish: make(chan int),
	}
}

func (parser EpubParser) Parser() {
	// 读取文件
	file, err := os.OpenFile("./file/"+parser.FileName+".txt", os.O_RDONLY, 0600)
	if err != nil {
		log.PrintErr(err.Error())
	}
	defer file.Close()

	reader := bufio.NewReader(file)
	// 前一行为空的标记
	emptyPreLineFlag := false
	var content []string
	var buffer []byte
	title := ""
	chapterCount := 0

	for {
		line, prefix, err := reader.ReadLine()
		// log.Println(line, prefix, err)
		if err != nil {
			if err == io.EOF {
				if len(line) != 0 {
					content = append(content, string(line))
				}

				parser.Chap <- EpubChapter{
					CurCount: chapterCount,
					Title:    title,
					Content:  content,
				}

				parser.ParserFinish <- chapterCount
				break
			}
			log.PrintErr(err.Error())
			break
		}

		// isPrefix = true
		if prefix {
			// 表示缓冲区满 还有下一行
			buffer = append(buffer, line...)
			continue
		} else {
			buffer = line
		}

		if emptyPreLineFlag {
			// 判断是否是 标题
			if strings.Index(string(buffer), "第") == 0 &&
				(strings.Index(string(buffer), "章") != -1 ||
					strings.Index(string(buffer), "卷") != -1) {
				// log.Println(string(buffer))

				if len(content) != 0 {
					// 不是第一章
					// 传输 上一章节的内容 让生成方处理
					//log.PrintErr(fmt.Sprintf("%p %p %p", chapterCount, title, content))
					parser.Chap <- EpubChapter{
						CurCount: chapterCount,
						Title:    title,
						Content:  content,
					}
					content = []string{}
				}

				title = string(buffer)
				chapterCount++
				log.Println("章节数:", chapterCount)
				emptyPreLineFlag = false
				continue
			}
		}

		if len(buffer) == 0 {
			// 标题 章节前面需要是一个空行
			emptyPreLineFlag = true
		} else {
			content = append(content, string(buffer))
			emptyPreLineFlag = false
		}
	}
}

// ------------------------- 生成 -----------------------

func (parser EpubParser) Gen() {
	parser.genMeta()
	parser.genMimetype()
	parser.genOebps()
	list := make([]TableContentItem, 0)
	countList := make([]int, 0)

	finish := 0
	for {
		select {
		case c := <-parser.Chap:
			parser.genXhtml(c)

			list = append(list, TableContentItem{
				CurCount: c.CurCount,
				Title:    c.Title,
			})
			countList = append(countList, c.CurCount)

			finish++
			log.Println(finish, parser.ListSize)
			//if finish == 217 {
			//	goto end
			//}
		case <-parser.ParserFinish:
			if len(parser.Chap) == 0 {
				goto end
			} else {
				c := <-parser.Chap
				parser.genXhtml(c)

				list = append(list, TableContentItem{
					CurCount: c.CurCount,
					Title:    c.Title,
				})
				countList = append(countList, c.CurCount)

				finish++
				log.Println(finish, parser.ListSize)

				go func() { parser.ParserFinish <- 1 }()
			}
		}
	}

end:
	log.Println(finish)

	parser.genTableContents(TableContent{
		Item: list,
	})

	parser.genOpf(countList)
	parser.genZipFile()
}

func (parser EpubParser) Gen2() {
	// META-INF
	parser.genMeta()

	// mimetype
	parser.genMimetype()

	// oebps
	parser.genOebps()
}

func (parser EpubParser) genMeta() {
	os.MkdirAll(parser.MetaInfPath, 0777)
	// META-INF
	templateFile, err := os.OpenFile("./template/container.xml", os.O_RDONLY, 0666)
	if err != nil {
		fmt.Println(err.Error())
	}
	defer templateFile.Close()

	targetFile, err := os.OpenFile(fmt.Sprintf("%s%s", parser.MetaInfPath, "container.xml"), os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err.Error())
	}
	io.Copy(targetFile, templateFile)
}

func (parser EpubParser) genMimetype() {
	// mimetype
	file, err := os.OpenFile("./"+parser.FileName+"/mimetype", os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Println(err.Error())
	}
	defer file.Close()
	file.Write([]byte("application/epub+zip"))
}

func (parser EpubParser) genOebps() {
	os.MkdirAll(parser.Oebps+"Text/", 0777)
	os.MkdirAll(parser.Oebps+"Styles/", 0777)

	parser.genStyles()

	//for {
	//	select {}
	//}

	//parser.genOpf()

}

// genOpf 利用模板生成content.opf文件
func (parser EpubParser) genOpf(countList []int) {

	manifests := make([]OpfManifest, 0)
	for _, v := range countList {
		manifests = append(manifests, OpfManifest{
			MediaType: "application/xhtml+xml",
			CurCount:  v,
		})
	}

	parser.DataMap.Manifest = manifests

	files, err := template.ParseFiles("./template/content.opf")
	if err != nil {
		log.PrintErr(err.Error())
	}

	buffer := &bytes.Buffer{}
	err = files.Execute(buffer, parser.DataMap)

	file, err := os.OpenFile(parser.Oebps+"content.opf", os.O_CREATE|os.O_WRONLY, 0777)
	if err != nil {
		log.PrintErr(err.Error())
	}
	defer file.Close()

	buffer.WriteTo(file)
}

func (parser EpubParser) genXhtml(chapter EpubChapter) {
	files, err := template.ParseFiles("./template/template.xhtml")
	if err != nil {
		log.PrintErr(err.Error())
	}

	chapter.FileName = parser.FileName

	buffer := &bytes.Buffer{}
	err = files.Execute(buffer, chapter)

	file, err := os.OpenFile(fmt.Sprintf("%sText/text%d.xhtml", parser.Oebps, chapter.CurCount), os.O_CREATE|os.O_WRONLY, 0777)
	if err != nil {
		log.PrintErr(err.Error())
	}
	defer file.Close()

	buffer.WriteTo(file)
}

func (parser EpubParser) genStyles() {
	// Styles
	styleFile1, err := os.OpenFile("./template/style0001.css", os.O_RDONLY, 0666)
	styleFile2, err := os.OpenFile("./template/style0002.css", os.O_RDONLY, 0666)
	if err != nil {
		fmt.Println(err.Error())
	}
	defer styleFile1.Close()
	defer styleFile2.Close()

	targetStyleFile1, err := os.OpenFile(fmt.Sprintf("%sStyles/style0001.css", parser.Oebps), os.O_CREATE|os.O_WRONLY, 0666)
	targetStyleFile2, err := os.OpenFile(fmt.Sprintf("%sStyles/style0002.css", parser.Oebps), os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err.Error())
	}
	defer targetStyleFile1.Close()

	defer targetStyleFile2.Close()

	io.Copy(targetStyleFile1, styleFile1)
	io.Copy(targetStyleFile2, styleFile2)
}

// 生成目录
func (parser EpubParser) genTableContents(content TableContent) {
	files, err := template.ParseFiles("./template/TableContents.xhtml")
	if err != nil {
		log.PrintErr(err.Error())
	}

	content.FileName = parser.FileName

	buffer := &bytes.Buffer{}
	err = files.Execute(buffer, content)

	file, err := os.OpenFile(fmt.Sprintf("%sText/TableContent.xhtml", parser.Oebps), os.O_CREATE|os.O_WRONLY, 0777)
	if err != nil {
		log.PrintErr(err.Error())
	}
	defer file.Close()

	buffer.WriteTo(file)

	// ncx
	ncxTemplateFile, err := template.ParseFiles("./template/toc.ncx")
	if err != nil {
		log.PrintErr(err.Error())
	}

	buffer = &bytes.Buffer{}
	err = ncxTemplateFile.Execute(buffer, content)

	ncxFile, err := os.OpenFile(fmt.Sprintf("%stoc.ncx", parser.Oebps), os.O_CREATE|os.O_WRONLY, 0777)
	if err != nil {
		log.PrintErr(err.Error())
	}
	defer ncxFile.Close()

	buffer.WriteTo(ncxFile)
}

func (parser EpubParser) genZipFile() {
	//d, _ := os.Create(parser.FileName + ".epub")
	//defer d.Close()
	//
	//w := zip.NewWriter(d)
	//defer w.Close()
	//
	//files := make([]string, 0)
	//files = append(files, fmt.Sprintf("./%s/mimetype", parser.FileName))
	//
	//for _, file := range files {
	//	err := compress(file, "", w)
	//	if err != nil {
	//		return err
	//	}
	//}
	//return nil

}
